package tunnel

import (
	"context"
	"fmt"
	"log"
	"net"
	"sync"
	"sync/atomic"
	"time"

	"github.com/quic-go/quic-go"
)

// QUICPooledConnection 池化的QUIC连接
type QUICPooledConnection struct {
	Conn          *quic.Conn   // 🔧 使用*quic.Conn具体类型
	ConnectionID  string       // 连接唯一ID
	ProtocolType  ProtocolType // 协议类型
	ActiveStreams int32        // 当前活跃Stream数（原子操作）
	TotalStreams  int64        // 历史总Stream数（原子操作）
	LastUsedTime  time.Time    // 最后使用时间
	unhealthy     int32        // 不健康标记（0=健康, 1=不健康）
	unhealthyTime time.Time    // 标记为不健康的时间

	// 🔥 性能统计
	avgWriteDuration time.Duration // 平均WriteMessage耗时
	totalWrites      int64         // WriteMessage总次数

	// 🔥🔥🔥 关键优化：连接就绪状态
	lastStreamOpenTime  time.Time // 最后一次成功打开Stream的时间
	consecutiveFailures int32     // 连续失败次数（原子操作）

	mu sync.RWMutex // 保护LastUsedTime、unhealthyTime、avgWriteDuration、lastStreamOpenTime
}

// IncrementStreams 增加活跃Stream计数
func (c *QUICPooledConnection) IncrementStreams() {
	atomic.AddInt32(&c.ActiveStreams, 1)
	atomic.AddInt64(&c.TotalStreams, 1)
	c.mu.Lock()
	c.LastUsedTime = time.Now()
	c.mu.Unlock()
}

// DecrementStreams 减少活跃Stream计数
func (c *QUICPooledConnection) DecrementStreams() {
	atomic.AddInt32(&c.ActiveStreams, -1)
}

// GetActiveStreams 获取当前活跃Stream数
func (c *QUICPooledConnection) GetActiveStreams() int32 {
	return atomic.LoadInt32(&c.ActiveStreams)
}

// GetTotalStreams 获取历史总Stream数
func (c *QUICPooledConnection) GetTotalStreams() int64 {
	return atomic.LoadInt64(&c.TotalStreams)
}

// MarkUnhealthy 标记连接为不健康
func (c *QUICPooledConnection) MarkUnhealthy() {
	if atomic.CompareAndSwapInt32(&c.unhealthy, 0, 1) {
		c.mu.Lock()
		c.unhealthyTime = time.Now()
		c.mu.Unlock()
		log.Printf("⚠️  [连接池] 标记连接不健康: ConnID=%s", c.ConnectionID[:8]+"...")
	}
}

// IsHealthy 检查连接是否健康（🚀 非阻塞快速检查）
func (c *QUICPooledConnection) IsHealthy() bool {
	// 🚀 优化：只检查标志位，不做任何阻塞操作
	return atomic.LoadInt32(&c.unhealthy) == 0
}

// TryRecover 尝试恢复不健康的连接（异步执行，不阻塞）
func (c *QUICPooledConnection) TryRecover() {
	if atomic.LoadInt32(&c.unhealthy) == 0 {
		return // 已经健康
	}

	// 检查是否到了恢复时间（5分钟）
	c.mu.RLock()
	unhealthyDuration := time.Since(c.unhealthyTime)
	c.mu.RUnlock()

	if unhealthyDuration < 5*time.Minute {
		return // 还没到恢复时间
	}

	// 🚀 异步尝试恢复，不阻塞调用方
	go func() {
		ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) // 缩短到500ms
		defer cancel()

		if c.Conn != nil {
			// 尝试打开一个测试Stream
			stream, err := c.Conn.OpenStreamSync(ctx)
			if err == nil {
				stream.Close() // 立即关闭测试Stream

				// 恢复健康状态
				atomic.StoreInt32(&c.unhealthy, 0)
				log.Printf("✅ [连接池] 连接已自动恢复健康: ConnID=%s, 不健康时长=%.1f分钟",
					c.ConnectionID[:8]+"...", unhealthyDuration.Minutes())
			}
		}
	}()
}

// RecordWriteDuration 记录WriteMessage耗时（使用指数移动平均）
func (c *QUICPooledConnection) RecordWriteDuration(duration time.Duration) {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.totalWrites++

	// 指数移动平均（EMA）：新值权重20%，旧值权重80%
	alpha := 0.2
	if c.totalWrites == 1 {
		c.avgWriteDuration = duration
	} else {
		c.avgWriteDuration = time.Duration(
			float64(c.avgWriteDuration)*(1-alpha) +
				float64(duration)*alpha,
		)
	}

	// 警告：如果平均写入耗时超过5秒
	if c.avgWriteDuration > 5*time.Second {
		log.Printf("⚠️  [连接池] 连接写入性能下降: ConnID=%s, 平均耗时=%.2fs",
			c.ConnectionID[:8]+"...", c.avgWriteDuration.Seconds())
	}
}

// RecordStreamOpenSuccess 记录Stream打开成功（重置连续失败计数）
func (c *QUICPooledConnection) RecordStreamOpenSuccess() {
	c.mu.Lock()
	c.lastStreamOpenTime = time.Now()
	c.mu.Unlock()
	atomic.StoreInt32(&c.consecutiveFailures, 0)
}

// RecordStreamOpenFailure 记录Stream打开失败
func (c *QUICPooledConnection) RecordStreamOpenFailure() {
	failures := atomic.AddInt32(&c.consecutiveFailures, 1)
	// 如果连续失败3次以上，标记为不健康
	if failures >= 3 {
		c.MarkUnhealthy()
	}
}

// GetConsecutiveFailures 获取连续失败次数
func (c *QUICPooledConnection) GetConsecutiveFailures() int32 {
	return atomic.LoadInt32(&c.consecutiveFailures)
}

// GetLastStreamOpenTime 获取最后一次成功打开Stream的时间
func (c *QUICPooledConnection) GetLastStreamOpenTime() time.Time {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.lastStreamOpenTime
}

// GetAvgWriteDuration 获取平均WriteMessage耗时
func (c *QUICPooledConnection) GetAvgWriteDuration() time.Duration {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.avgWriteDuration
}

// GetTotalWrites 获取WriteMessage总次数
func (c *QUICPooledConnection) GetTotalWrites() int64 {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.totalWrites
}

// QUICConnectionPool QUIC连接池
type QUICConnectionPool struct {
	tunnelID    string
	connections map[ProtocolType][]*QUICPooledConnection // 按协议类型分组
	mu          sync.RWMutex
	ctx         context.Context
	cancel      context.CancelFunc
	roundRobin  map[ProtocolType]*int32 // 🚀 轮询索引（每个协议一个）
}

// NewQUICConnectionPool 创建QUIC连接池
func NewQUICConnectionPool(tunnelID string) *QUICConnectionPool {
	ctx, cancel := context.WithCancel(context.Background())
	pool := &QUICConnectionPool{
		tunnelID:    tunnelID,
		connections: make(map[ProtocolType][]*QUICPooledConnection),
		ctx:         ctx,
		cancel:      cancel,
		roundRobin:  make(map[ProtocolType]*int32), // 🚀 初始化轮询索引
	}

	// 🔥🔥🔥 暂时禁用健康检查
	// 问题：Context().Done()不是可靠的连接状态指示器
	// QUIC库内部的Context可能因为各种原因被取消，但连接实际上还是活跃的
	// 解决方案：移除主动健康检查，只在实际使用时发现连接不可用才处理
	// go pool.healthCheck() // ❌ 禁用

	return pool
}

// AddConnection 添加连接到池中
func (p *QUICConnectionPool) AddConnection(conn *quic.Conn, connID string, protocolType ProtocolType) {
	p.mu.Lock()
	defer p.mu.Unlock()

	pooledConn := &QUICPooledConnection{
		Conn:          conn,
		ConnectionID:  connID,
		ProtocolType:  protocolType,
		ActiveStreams: 0,
		TotalStreams:  0,
		LastUsedTime:  time.Now(),
	}

	p.connections[protocolType] = append(p.connections[protocolType], pooledConn)
	log.Printf("🔗 [连接池] 添加连接: TunnelID=%s, ConnID=%s, 协议=%s, 当前连接数=%d",
		p.tunnelID[:8]+"...", connID[:8]+"...", protocolType, len(p.connections[protocolType]))
}

// GetConnection 获取连接（🚀🚀🚀 视频分片优化：真正的负载均衡）
func (p *QUICConnectionPool) GetConnection(protocolType ProtocolType) (*QUICPooledConnection, error) {
	// 🚀 优化1：只在读取连接列表时持有锁，然后立即释放
	p.mu.RLock()
	conns, exists := p.connections[protocolType]
	if !exists || len(conns) == 0 {
		p.mu.RUnlock()
		return nil, fmt.Errorf("没有可用的%s协议连接", protocolType)
	}

	// 🚀 优化2：复制连接切片，避免长时间持有锁
	connsCopy := make([]*QUICPooledConnection, len(conns))
	copy(connsCopy, conns)
	p.mu.RUnlock()

	// 🚀 优化3：在锁外进行健康检查和选择逻辑（不阻塞其他请求）
	// 过滤出健康连接
	healthyConns := make([]*QUICPooledConnection, 0, len(connsCopy))
	for _, conn := range connsCopy {
		if conn.IsHealthy() {
			healthyConns = append(healthyConns, conn)
		} else {
			// 🚀 优化4：异步尝试恢复不健康连接（不阻塞）
			conn.TryRecover()
		}
	}

	// 如果没有健康连接，使用所有连接作为兜底
	if len(healthyConns) == 0 {
		log.Printf("⚠️  [连接池] 所有连接都不健康，使用所有连接")
		healthyConns = connsCopy
	}

	// 🔥🔥🔥 关键优化：智能负载均衡（解决AcceptStream阻塞延迟问题）
	// 策略：
	// 1. 优先选择"最近成功打开Stream"的连接（说明客户端AcceptStream在活跃监听）
	// 2. 避免选择长时间没有成功打开Stream的连接（可能在阻塞等待AcceptStream）
	// 3. 跳过连续失败的连接
	// 4. 使用轮询确保负载均衡

	// 初始化轮询索引（如果不存在）
	p.mu.RLock()
	if p.roundRobin[protocolType] == nil {
		p.mu.RUnlock()
		p.mu.Lock()
		if p.roundRobin[protocolType] == nil {
			idx := int32(0)
			p.roundRobin[protocolType] = &idx
		}
		p.mu.Unlock()
		p.mu.RLock()
	}
	p.mu.RUnlock()

	// 🚀🚀🚀 智能筛选：过滤出"就绪"的连接
	// "就绪"定义：
	// 1. 最近10秒内成功打开过Stream（说明AcceptStream在监听）
	// 2. 连续失败次数 < 2
	now := time.Now()
	readyConns := make([]*QUICPooledConnection, 0, len(healthyConns))
	for _, conn := range healthyConns {
		lastOpenTime := conn.GetLastStreamOpenTime()
		failures := conn.GetConsecutiveFailures()

		// 检查是否就绪
		isRecentlyActive := !lastOpenTime.IsZero() && now.Sub(lastOpenTime) < 10*time.Second
		hasLowFailures := failures < 2

		if isRecentlyActive && hasLowFailures {
			readyConns = append(readyConns, conn)
		}
	}

	// 如果没有"就绪"的连接，使用所有健康连接（兜底策略）
	candidateConns := readyConns
	if len(readyConns) == 0 {
		log.Printf("⚠️  [连接池] 没有就绪连接，使用所有健康连接 (健康连接数=%d)", len(healthyConns))
		candidateConns = healthyConns
	}

	// 🚀 使用原子操作进行轮询，确保线程安全且不阻塞
	currentIdx := atomic.AddInt32(p.roundRobin[protocolType], 1) - 1
	selectedIdx := int(currentIdx) % len(candidateConns)
	bestConn := candidateConns[selectedIdx]

	// 找到bestConn在原conns中的真实索引（用于日志）
	realIdx := 0
	for i, conn := range connsCopy {
		if conn.ConnectionID == bestConn.ConnectionID {
			realIdx = i
			break
		}
	}

	lastOpenTime := bestConn.GetLastStreamOpenTime()
	timeSinceLastOpen := time.Duration(0)
	if !lastOpenTime.IsZero() {
		timeSinceLastOpen = now.Sub(lastOpenTime)
	}

	log.Printf("🎯 [连接池] 智能选择连接: ConnID=%s, 索引=%d/%d, 就绪=%d/%d, 活跃Stream=%d, 失败=%d, 最近打开=%.1fs前",
		bestConn.ConnectionID[:8]+"...", realIdx+1, len(connsCopy),
		len(readyConns), len(healthyConns),
		bestConn.GetActiveStreams(), bestConn.GetConsecutiveFailures(), timeSinceLastOpen.Seconds())

	return bestConn, nil
}

// RemoveConnection 移除连接
func (p *QUICConnectionPool) RemoveConnection(connID string, protocolType ProtocolType) {
	p.mu.Lock()
	defer p.mu.Unlock()

	conns, exists := p.connections[protocolType]
	if !exists {
		return
	}

	for i, conn := range conns {
		if conn.ConnectionID == connID {
			p.connections[protocolType] = append(conns[:i], conns[i+1:]...)
			log.Printf("🔌 [连接池] 移除连接: ConnID=%s, 协议=%s, 剩余连接数=%d",
				connID[:8]+"...", protocolType, len(p.connections[protocolType]))
			break
		}
	}
}

// GetStats 获取连接池统计信息
func (p *QUICConnectionPool) GetStats() map[ProtocolType]PoolStats {
	p.mu.RLock()
	defer p.mu.RUnlock()

	stats := make(map[ProtocolType]PoolStats)

	for protocolType, conns := range p.connections {
		var totalActive int32
		var totalHistorical int64
		var minActive, maxActive int32 = 999999, 0

		for _, conn := range conns {
			active := conn.GetActiveStreams()
			totalActive += active
			totalHistorical += conn.GetTotalStreams()

			if active < minActive {
				minActive = active
			}
			if active > maxActive {
				maxActive = active
			}
		}

		if len(conns) > 0 {
			stats[protocolType] = PoolStats{
				TotalConnections:   len(conns),
				TotalActiveStreams: totalActive,
				TotalStreams:       totalHistorical,
				MinActiveStreams:   minActive,
				MaxActiveStreams:   maxActive,
				AvgActiveStreams:   float64(totalActive) / float64(len(conns)),
			}
		}
	}

	return stats
}

// PoolStats 连接池统计信息
type PoolStats struct {
	TotalConnections   int     // 总连接数
	TotalActiveStreams int32   // 总活跃Stream数
	TotalStreams       int64   // 历史总Stream数
	MinActiveStreams   int32   // 最小活跃Stream数
	MaxActiveStreams   int32   // 最大活跃Stream数
	AvgActiveStreams   float64 // 平均活跃Stream数
}

// CleanupUnhealthyConnections 清理不健康的连接
func (p *QUICConnectionPool) CleanupUnhealthyConnections() int {
	p.mu.Lock()
	defer p.mu.Unlock()

	removedCount := 0

	// 遍历所有协议类型的连接
	for protocolType, connections := range p.connections {
		healthyConns := make([]*QUICPooledConnection, 0, len(connections))

		for _, conn := range connections {
			if conn.IsHealthy() {
				healthyConns = append(healthyConns, conn)
			} else {
				// 关闭不健康的连接
				log.Printf("🧹 [连接池] 清理不健康连接: ConnID=%s, TunnelID=%s, 协议=%d",
					conn.ConnectionID[:8]+"...", p.tunnelID[:8]+"...", protocolType)

				// 关闭QUIC连接
				if conn.Conn != nil {
					conn.Conn.CloseWithError(0, "unhealthy connection cleanup")
				}

				removedCount++
			}
		}

		// 更新连接列表（只保留健康的）
		p.connections[protocolType] = healthyConns
	}

	if removedCount > 0 {
		log.Printf("✅ [连接池] 清理完成: TunnelID=%s, 移除%d个不健康连接, 剩余%d个健康连接",
			p.tunnelID[:8]+"...", removedCount, p.GetSize())
	}

	return removedCount
}

// GetSize 获取连接池大小
func (p *QUICConnectionPool) GetSize() int {
	p.mu.RLock()
	defer p.mu.RUnlock()

	total := 0
	for _, connections := range p.connections {
		total += len(connections)
	}

	return total
}

// VerifyAndCleanupZombieConnections 主动验证并清理僵尸连接（用于客户端重启后的清理）
// 🔥 这个方法会主动尝试打开Stream来验证连接是否真的活跃
// 与CleanupUnhealthyConnections不同，这个方法会主动检测所有连接
func (p *QUICConnectionPool) VerifyAndCleanupZombieConnections() int {
	p.mu.Lock()
	defer p.mu.Unlock()

	removedCount := 0

	// 遍历所有协议类型的连接
	for protocolType, connections := range p.connections {
		healthyConns := make([]*QUICPooledConnection, 0, len(connections))

		for _, conn := range connections {
			// 🔥🔥🔥 关键修复：延长超时时间以适应客户端启动和网络延迟
			// 问题：客户端的AcceptStream可能需要2-5秒才能开始监听（启动监听器）
			// 解决：使用5秒超时打开Stream，2秒读超时等待响应

			isHealthy := false
			testCtx, testCancel := context.WithTimeout(context.Background(), 5*time.Second)
			testStream, err := conn.Conn.OpenStreamSync(testCtx)

			if err != nil {
				// 无法打开Stream，连接已死
				log.Printf("🧹 [主动验证] 无法打开Stream: ConnID=%s, 错误=%v",
					conn.ConnectionID[:8]+"...", err)
				testCancel()
			} else {
				// 能打开Stream，但还要测试客户端是否能响应
				// 发送一个0字节的测试写入，看是否会立即报错
				_, writeErr := testStream.Write([]byte{0x00})
				if writeErr != nil {
					// 写入失败，连接已死
					log.Printf("🧹 [主动验证] Stream写入失败: ConnID=%s, 错误=%v",
						conn.ConnectionID[:8]+"...", writeErr)
					testStream.Close()
					testCancel()
				} else {
					// 写入成功，等待2秒看客户端是否会关闭Stream（客户端应该会因为协议错误关闭）
					// 或者设置读超时，如果客户端没反应也说明死了
					testStream.SetReadDeadline(time.Now().Add(2 * time.Second))
					buf := make([]byte, 1)
					_, readErr := testStream.Read(buf)

					// 如果读取超时，说明客户端AcceptStream没在工作 = 僵尸连接
					// 如果读取到数据或EOF，说明客户端还活着
					if readErr != nil {
						if netErr, ok := readErr.(net.Error); ok && netErr.Timeout() {
							// 超时 = 客户端AcceptStream没工作 = 僵尸连接
							log.Printf("🧹 [主动验证] 客户端AcceptStream超时(2秒): ConnID=%s",
								conn.ConnectionID[:8]+"...")
						} else {
							// 其他错误，但至少客户端还在响应
							isHealthy = true
						}
					} else {
						// 读取到数据，客户端活着
						isHealthy = true
					}

					testStream.Close()
					testCancel()
				}
			}

			if !isHealthy {
				// 僵尸连接，清理
				log.Printf("🧹 [主动验证] 检测到僵尸连接: ConnID=%s, TunnelID=%s, 协议=%d",
					conn.ConnectionID[:8]+"...", p.tunnelID[:8]+"...", protocolType)

				// 关闭QUIC连接
				if conn.Conn != nil {
					conn.Conn.CloseWithError(0, "zombie connection cleanup")
				}

				removedCount++
			} else {
				// 连接健康
				healthyConns = append(healthyConns, conn)
			}
		}

		// 更新连接列表（只保留健康的）
		p.connections[protocolType] = healthyConns
	}

	if removedCount > 0 {
		log.Printf("✅ [主动验证] 清理完成: TunnelID=%s, 移除%d个僵尸连接, 剩余%d个健康连接",
			p.tunnelID[:8]+"...", removedCount, p.GetSize())
	}

	return removedCount
}
